"""
Admin blueprint for authenticated routes.

Routes:
- GET /admin/login : Show login form
- POST /admin/login : Process login
- GET /admin/logout : Logout and clear session
- GET /admin/dashboard : Admin dashboard (requires auth)
- GET /admin/create : Show create documentation form (requires auth)
- POST /admin/create : Process documentation creation (requires auth)
"""
from flask import Blueprint, render_template, request, redirect, url_for, flash, session
from werkzeug.utils import secure_filename
import os

from app.models import db, Administrator, Documentation
from app.auth import login_required, get_current_admin, log_audit_entry, get_request_details

admin_bp = Blueprint('admin', __name__)

# Allowed file extensions for upload
ALLOWED_EXTENSIONS = {'.md', '.html', '.txt'}

# Format mapping from file extension
FORMAT_MAP = {
    '.md': 'markdown',
    '.html': 'html',
    '.txt': 'text'
}


def allowed_file(filename):
    """Check if file extension is allowed."""
    return os.path.splitext(filename)[1].lower() in ALLOWED_EXTENSIONS


@admin_bp.route('/login', methods=['GET', 'POST'])
def login():
    """
    Admin login page and authentication handler.

    GET: Display login form
    POST: Process login credentials
    """
    # If already logged in, redirect to dashboard
    if 'admin_id' in session:
        return redirect(url_for('admin.dashboard'))

    if request.method == 'POST':
        username = request.form.get('username', '').strip()
        password = request.form.get('password', '')

        if not username or not password:
            flash('请输入用户名和密码', 'error')
            return render_template('admin/login.html')

        # Find administrator
        admin = Administrator.query.filter_by(username=username).first()

        if admin and admin.check_password(password):
            # Successful login
            session['admin_id'] = admin.id
            session['admin_username'] = admin.username
            session.permanent = True  # Use PERMANENT_SESSION_LIFETIME

            # Log successful login
            details = get_request_details()
            log_audit_entry(admin.id, 'login', details=details)

            flash(f'欢迎回来, {admin.username}!', 'success')

            # Redirect to next page or dashboard
            next_page = request.args.get('next')
            if next_page and next_page.startswith('/'):
                return redirect(next_page)
            return redirect(url_for('admin.dashboard'))
        else:
            # Failed login
            flash('用户名或密码错误', 'error')

    return render_template('admin/login.html')


@admin_bp.route('/logout')
@login_required
def logout():
    """
    Logout admin user and clear session.
    """
    admin_id = session.get('admin_id')

    if admin_id:
        # Log logout
        log_audit_entry(admin_id, 'logout')

    # Clear session
    session.pop('admin_id', None)
    session.pop('admin_username', None)

    flash('已成功退出登录', 'success')
    return redirect(url_for('admin.login'))


@admin_bp.route('/dashboard')
@login_required
def dashboard():
    """
    Admin dashboard - overview and navigation.
    """
    admin = get_current_admin()

    # Get statistics
    doc_count = Documentation.query.count()
    recent_docs = Documentation.query.order_by(Documentation.created_at.desc()).limit(5).all()

    return render_template(
        'admin/dashboard.html',
        admin=admin,
        doc_count=doc_count,
        recent_docs=recent_docs
    )


@admin_bp.route('/create', methods=['GET', 'POST'])
@login_required
def create():
    """
    Create new documentation.

    GET: Display creation form
    POST: Process form submission (text input or file upload)
    """
    if request.method == 'POST':
        admin = get_current_admin()
        title = request.form.get('title', '').strip()

        # Validation
        if not title:
            flash('请输入文档标题', 'error')
            return render_template('admin/create.html')

        if len(title) > 200:
            flash('标题长度不能超过200个字符', 'error')
            return render_template('admin/create.html')

        # Check if file upload or text input
        uploaded_file = request.files.get('file')
        rich_content = request.form.get('rich_content', '').strip()

        if uploaded_file and uploaded_file.filename:
            # File upload path
            if not allowed_file(uploaded_file.filename):
                flash('只允许上传 .md, .html, .txt 文件', 'error')
                return render_template('admin/create.html')

            # Read file content
            try:
                content = uploaded_file.read().decode('utf-8')
            except UnicodeDecodeError:
                flash('文件编码错误，请使用 UTF-8 编码', 'error')
                return render_template('admin/create.html')

            # Determine format from file extension
            ext = os.path.splitext(uploaded_file.filename)[1].lower()
            format_type = FORMAT_MAP.get(ext, 'text')

        elif rich_content:
            # Rich editor content (HTML format)
            content = rich_content
            format_type = 'html'

        else:
            # Text input path
            content = request.form.get('content', '').strip()
            format_type = request.form.get('format', 'markdown')

            if not content:
                flash('请输入文档内容或上传文件', 'error')
                return render_template('admin/create.html')

            if format_type not in ['markdown', 'html', 'text']:
                format_type = 'markdown'

        # Get category (optional)
        category = request.form.get('category', '').strip() or None
        if category and len(category) > 100:
            category = category[:100]

        # Create documentation
        doc = Documentation(
            title=title,
            content=content,
            format=format_type,
            category=category
        )

        try:
            db.session.add(doc)
            db.session.commit()

            # Log creation
            log_audit_entry(
                admin.id,
                'create_doc',
                resource_type='documentation',
                resource_id=doc.id,
                details={'title': title, 'format': format_type}
            )

            flash(f'文档《{title}》创建成功！', 'success')
            return redirect(url_for('public.view_document', id=doc.id))

        except Exception as e:
            db.session.rollback()
            flash(f'创建失败: {str(e)}', 'error')

    return render_template('admin/create.html')


@admin_bp.route('/change-password', methods=['GET', 'POST'])
@login_required
def change_password():
    """
    Change admin password page.

    GET: Display change password form
    POST: Process password change
    """
    admin = get_current_admin()

    if request.method == 'POST':
        current_password = request.form.get('current_password', '')
        new_password = request.form.get('new_password', '')
        confirm_password = request.form.get('confirm_password', '')

        # Validate current password
        if not admin.check_password(current_password):
            flash('当前密码不正确', 'error')
            return render_template('admin/change_password.html')

        # Validate new password
        if len(new_password) < 8:
            flash('新密码至少需要8个字符', 'error')
            return render_template('admin/change_password.html')

        if new_password != confirm_password:
            flash('两次输入的新密码不一致', 'error')
            return render_template('admin/change_password.html')

        if new_password == current_password:
            flash('新密码不能与当前密码相同', 'error')
            return render_template('admin/change_password.html')

        # Update password
        try:
            admin.set_password(new_password)
            db.session.commit()

            # Log password change
            log_audit_entry(
                admin.id,
                'change_password',
                details=get_request_details()
            )

            flash('密码修改成功！', 'success')
            return redirect(url_for('admin.dashboard'))

        except Exception as e:
            db.session.rollback()
            flash(f'密码修改失败: {str(e)}', 'error')

    return render_template('admin/change_password.html')


@admin_bp.route('/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit(id):
    """
    Edit documentation page.

    GET: Display edit form with existing content
    POST: Process documentation update
    """
    admin = get_current_admin()
    doc = Documentation.query.get_or_404(id)

    if request.method == 'POST':
        title = request.form.get('title', '').strip()

        if not title:
            flash('标题不能为空', 'error')
            return render_template('admin/edit.html', doc=doc)

        if len(title) > 200:
            flash('标题长度不能超过200个字符', 'error')
            return render_template('admin/edit.html', doc=doc)

        # Get content and format
        content = request.form.get('content', '').strip()
        format_type = request.form.get('format', 'markdown')

        if not content:
            flash('文档内容不能为空', 'error')
            return render_template('admin/edit.html', doc=doc)

        if format_type not in ['markdown', 'html', 'text']:
            format_type = 'markdown'

        # Get category (optional)
        category = request.form.get('category', '').strip() or None
        if category and len(category) > 100:
            category = category[:100]

        # Update documentation
        old_data = {
            'title': doc.title,
            'format': doc.format,
            'category': doc.category,
            'content_length': len(doc.content)
        }

        doc.title = title
        doc.content = content
        doc.format = format_type
        doc.category = category

        try:
            db.session.commit()

            # Log update
            log_audit_entry(
                admin.id,
                'update_doc',
                resource_type='documentation',
                resource_id=doc.id,
                details={
                    'old': old_data,
                    'new': {'title': title, 'format': format_type, 'content_length': len(content)}
                }
            )

            flash(f'文档《{title}》更新成功！', 'success')
            return redirect(url_for('public.view_document', id=doc.id))

        except Exception as e:
            db.session.rollback()
            flash(f'更新失败: {str(e)}', 'error')

    return render_template('admin/edit.html', doc=doc)


@admin_bp.route('/delete/<int:id>', methods=['POST'])
@login_required
def delete(id):
    """
    Delete documentation.

    Args:
        id (int): Documentation ID

    Returns:
        Redirect to dashboard with success/error message
    """
    admin = get_current_admin()
    doc = Documentation.query.get_or_404(id)

    # Store doc info before deletion
    doc_title = doc.title
    doc_id = doc.id

    try:
        db.session.delete(doc)
        db.session.commit()

        # Log deletion
        log_audit_entry(
            admin.id,
            'delete_doc',
            resource_type='documentation',
            resource_id=doc_id,
            details={'title': doc_title}
        )

        flash(f'文档《{doc_title}》已删除', 'success')
        return redirect(url_for('admin.dashboard'))

    except Exception as e:
        db.session.rollback()
        flash(f'删除失败: {str(e)}', 'error')
        return redirect(url_for('admin.dashboard'))


@admin_bp.route('/toggle-lock/<int:id>', methods=['POST'])
@login_required
def toggle_lock(id):
    """
    Toggle document lock status.

    Args:
        id (int): Documentation ID

    Returns:
        Redirect to dashboard with success/error message
    """
    from datetime import datetime

    admin = get_current_admin()
    doc = Documentation.query.get_or_404(id)

    try:
        if doc.is_locked:
            # Unlock document
            doc.is_locked = False
            doc.locked_by = None
            doc.locked_at = None
            action = 'unlock_doc'
            message = f'文档《{doc.title}》已解锁'
        else:
            # Lock document
            doc.is_locked = True
            doc.locked_by = admin.id
            doc.locked_at = datetime.utcnow()
            action = 'lock_doc'
            message = f'文档《{doc.title}》已锁定'

        db.session.commit()

        # Log action
        log_audit_entry(
            admin.id,
            action,
            resource_type='documentation',
            resource_id=doc.id,
            details={'title': doc.title, 'is_locked': doc.is_locked}
        )

        flash(message, 'success')
        return redirect(url_for('admin.dashboard'))

    except Exception as e:
        db.session.rollback()
        flash(f'操作失败: {str(e)}', 'error')
        return redirect(url_for('admin.dashboard'))



